New Rails beta release, immutable option in http_cache_forever and more | This Week in Rails
https://world.hey.com/this.week.in.rails/new-rails-beta-release-immutable-option-in-http_cache_forever-and-more-d244a0c2
Release v7.2.0.beta3 · rails/rails · GitHub
v7.2.0.beta3 がリリースされました
Make http_cache_forever use immutable: true by natematykiewicz · Pull Request #52283 · rails/rails · GitHub
ActionPackに関する変更です
http_cache_forever というメソッドがあります
https://api.rubyonrails.org/classes/ActionController/ConditionalGet.html#method-i-http_cache_forever
HTTPレスポンスが決して変更されない場合に利用すると便利なメソッドです
今回のプルリクエストでは、このメソッドの内部実装で immutable: true オプションを利用するようになりました
このオプションについては第26回のエピソードでも取り上げました
#026: immutable cache header, local assigns in view template, ActiveStorage::Service::MirrorService - tanaken on Rails - LISTEN
Immutable Rails Cache Header, Local Assigns in Strict Local Templates, Threaded Active Storage Mirror Service | This Week in Rails#667f74734492e80000448ebe
今回のプルリクエスト以前は expires_in 100.years として有効期限が遠い未来に設定されたキャッシュ、という状態でしたが、immutable: true を指定することでそのリソースが変更されないことを明示的にブラウザに伝えることができます
i18n - Do not watch translations from gems when reloading is enabled by Schwad · Pull Request #52271 · rails/rails · GitHub
ActiveSupportに関する変更です
I18nを初期化する際の読み込み時間の高速化をしています
具体的には、翻訳ファイルの変更時に翻訳を自動再読み込みする機能が有効になっているとき、gem内の翻訳ファイルを監視の対象外としています
gemを利用するアプリケーションがgem内の翻訳ファイルを書き換えることはないので監視の対象外にしても問題はないためです
これにより監視対象が減るため、高速化につながります
なお、Railsアプリケーションのファイルの更新検出を再読み込みに関する設定は次のとおりです
https://railsguides.jp/configuring.html#config-enable-reloading
config.enable_reloadingがtrueの場合、アプリケーションのクラスとモジュールが変更されると、Webリクエスト間に再読み込みされます。 デフォルトは development環境ではtrue、production環境ではfalseです。
https://railsguides.jp/configuring.html#config-reload-classes-only-on-change
トラッキングしているファイルが変更された場合のみのクラス再読み込みを有効または無効にします。 デフォルトでは、すべての自動読み込みパスをトラッキングし、trueに設定されています。 このオプションは、config.enable_reloadingがfalseの場合は無視されます。
table:整理
No enable_reloading reload_classes_only_on_change クラスを再読み込みする条件
No.1 true true トラッキングしているファイルが変更された場合のみ
No.2 true false トラッキングしているファイルが変更されてない場合も
No.3 false - 再読み込みしない
Fix #48688 Duplicate callback execution when child autosaves parent with has_one and belongs_to by joshuay03 · Pull Request #49847 · rails/rails · GitHub
ActiveRecordに関する変更です
親子関係のあるモデルについて、子モデルのレコードと同時に親モデルのレコードを作成する場合に、子モデルに対して同じコールバックが2回ずつ呼ばれる不具合がありました
対象のコールバックは次の4つです
before_validation, after_validation, before_save, after_save
具体例は次のとおりです
Callbacks called twice when child accepts_nested_attributes_for parent · Issue #48688 · rails/rails · GitHub より抜粋
code:rb
class Post < ActiveRecord::Base
has_one :comment
before_validation :before_validation_callback_post
after_validation :after_validation_callback_post
before_save :before_save_callback_post
after_save :after_save_callback_post
before_create :before_create_callback_post
after_create :after_create_callback_post
def before_validation_callback_post
puts 'Post: before_validation_callback'
end
def after_validation_callback_post
puts 'Post: after_validation_callback'
end
def before_save_callback_post
puts 'Post: before_save_callback'
end
def after_save_callback_post
puts 'Post: after_save_callback'
end
def before_create_callback_post
puts 'Post: before_create_callback'
end
def after_create_callback_post
puts 'Post: after_create_callback'
end
end
class Comment < ActiveRecord::Base
belongs_to :post
accepts_nested_attributes_for :post
before_validation :before_validation_callback_comment
after_validation :after_validation_callback_comment
before_save :before_save_callback_comment
after_save :after_save_callback_comment
before_create :before_create_callback_comment
after_create :after_create_callback_comment
def before_validation_callback_comment
puts 'Comment: before_validation_callback'
end
def after_validation_callback_comment
puts 'Comment: after_validation_callback'
end
def before_save_callback_comment
puts 'Comment: before_save_callback'
end
def after_save_callback_comment
puts 'Comment: after_save_callback'
end
def before_create_callback_comment
puts 'Comment: before_create_callback'
end
def after_create_callback_comment
puts 'Comment: after_create_callback'
end
end
class BugTest < Minitest::Test
def test_association_stuff
Comment.create!(name: 'foo', post_attributes: {name: 'bar'})
end
end
code:sh
# Running:
Comment: before_validation_callback
Post: before_validation_callback
Post: after_validation_callback
Comment: after_validation_callback
Post: before_save_callback
Post: before_create_callback
D, 2023-07-07T12:17:20.661392 #2897 DEBUG -- : TRANSACTION (0.1ms) begin transaction
D, 2023-07-07T12:17:20.661656 #2897 DEBUG -- : Post Create (0.4ms) INSERT INTO "posts" ("name") VALUES (?) "name", "bar"
Comment: before_validation_callback
Comment: after_validation_callback
Comment: before_save_callback
Comment: before_create_callback
D, 2023-07-07T12:17:20.662908 #2897 DEBUG -- : Comment Create (0.1ms) INSERT INTO "comments" ("post_id", "name") VALUES (?, ?) "post_id", 1], ["name", "foo"
Comment: after_create_callback
Comment: after_save_callback
Post: after_create_callback
Post: after_save_callback
Comment: before_save_callback
Comment: after_save_callback
D, 2023-07-07T12:17:20.663528 #2897 DEBUG -- : TRANSACTION (0.1ms) commit transaction
今回のプルリクエストでは、重複しているコールバックが呼ばれないように修正しています